#include "js_base.hpp"
#include "data/editor_data.hpp"
#include "duk_console.h"
#include "duk_module_duktape.h"
#include "duk_print_alert.h"
#include "duktape.h"
#include "dukglue.h"
#include "dukglue/detail_primitive_types.h"
#include "scripting/extra/info_api.hpp"
#include "sql/types.hpp"
#include "utils/app_utils.hpp"
#include "utils/date_utils.hpp"
#include "utils/log.hpp"
#include "utils/path_utils.hpp"
#include "utils/shell_utils.hpp"

struct System {
    static void CopyText(std::string text)
    {
        ::CopyText(text);
    }

    static void I(std::string msg) { SendInfo(msg); }
    static void W(std::string msg) { SendWarning(msg); }
    static void E(std::string msg) { SendError(msg); }
    static void P(bool show) { ShowProgressDialog(show); }
    static void N(std::string msg, double ms) { SendNotification(msg, ms); }

    static void LogD(std::string msg) { log_printf("<script>", 1, LOG_LEVEL_DEBUG, "%s", msg.c_str()); }
    static void LogI(std::string msg) { log_printf("<script>", 1, LOG_LEVEL_INFO, "%s", msg.c_str()); }
    static void LogW(std::string msg) { log_printf("<script>", 1, LOG_LEVEL_WARN, "%s", msg.c_str()); }
    static void LogE(std::string msg) { log_printf("<script>", 1, LOG_LEVEL_ERROR, "%s", msg.c_str()); }
};

static void RegisterTypes(duk_context *ctx)
{
    // standard libs
    duk_print_alert_init (ctx, 0);
    duk_console_init (ctx, 0);
    duk_module_duktape_init (ctx);
    // log
    dukglue_register_function(ctx, &System::LogD, "log_d");
    dukglue_register_function(ctx, &System::LogI, "log_i");
    dukglue_register_function(ctx, &System::LogW, "log_w");
    dukglue_register_function(ctx, &System::LogE, "log_e");
    // dialog
    dukglue_register_function(ctx, &System::I, "show_info");
    dukglue_register_function(ctx, &System::W, "show_warning");
    dukglue_register_function(ctx, &System::E, "show_error");
    dukglue_register_function(ctx, &System::P, "show_progress");
    // notify
    dukglue_register_function(ctx, &System::N, "notify");
    // clipboard
    dukglue_register_function(ctx, &System::CopyText, "copy_text");

    // version
    dukglue_register_function(ctx, &GetAppVersionText, "app_version_str");
    dukglue_register_function(ctx, &GetAppVersionInfo, "app_version_info");
    dukglue_register_function(ctx, &GetAppVersionCode, "app_version_code");
    dukglue_register_function(ctx, &GetDataVersion, "data_version_str");
    dukglue_register_function(ctx, &GetDataVersionCode, "data_version_code");
    // path
    dukglue_register_function(ctx, &GetTempFilePath, "temp_path");
    dukglue_register_function(ctx, &GetAssetsPath, "asset_path");
    dukglue_register_function(ctx, &GetDataPath, "data_path");
    // shell utils
    dukglue_register_function(ctx, &ChooseFile, "choose_file");
    dukglue_register_function(ctx, &ChooseFiles, "choose_files");
    dukglue_register_function(ctx, &SaveFile, "save_file");
    dukglue_register_function(ctx, &PickFolder, "pick_folder");
    dukglue_register_function(ctx, &ShowLogFileContent, "show_logs");
    // date utils
    dukglue_register_function(ctx, &GetYesterday, "yestoday");
    dukglue_register_function(ctx, &GetToday, "today");
    dukglue_register_function(ctx, &GetTomorrow, "tommorrow");
    // app utils
    dukglue_register_function(ctx, &CreateWorkItem, "create_work");
    dukglue_register_function(ctx, &CreateWorkItemWithNote, "create_work_with_note");
    dukglue_register_function(ctx, &ShowStatistics, "show_statistics");

    // Tag
    dukglue_register_method<Tag>(ctx, +[](const Tag* t){ return t->tag_name; }, "name");
    dukglue_register_method<Tag>(ctx, +[](const Tag* t){ return t->tag_level; }, "level");
    dukglue_register_method<Tag>(ctx, +[](const Tag* t){ return t->tag_color; }, "color");

    // WorkItem
    dukglue_register_method<WorkItem>(ctx, +[](const WorkItem* x){ return x->create_date; }, "create_date");
    dukglue_register_method<WorkItem>(ctx, +[](const WorkItem* x){ return x->hour; }, "hour");
    dukglue_register_method<WorkItem>(ctx, +[](const WorkItem* x){ return x->comment; }, "comment");
    dukglue_register_method<WorkItem>(ctx, +[](const WorkItem* x){ return x->note; }, "note");

    // ItemNode
    dukglue_register_method<ItemNode>(ctx, +[](const ItemNode* x){ return &x->item; }, "item");
    dukglue_register_method<ItemNode>(ctx, +[](const ItemNode* x){ return x->item_tags; }, "tags");

}

JsScriptBase::JsScriptBase()
{
    ctx_ = duk_create_heap_default();
    RegisterTypes(ctx_);
}

JsScriptBase::~JsScriptBase()
{
    duk_destroy_heap(ctx_);
}
